#include "plc2llvm/PLCSymbolTable.h"

#include <utility>
#include <iostream>

void PLCSymbolTable::setImportSymbol(ImportScope *importSymbol) {
    this->importSymbol = importSymbol;
}

ImportScope *PLCSymbolTable::getImportSymbol() {
    return this->importSymbol;
}

void PLCSymbolTable::setScope(PLCScope *scope) {
    this->scope = scope;
}

PLCScope *PLCSymbolTable::getScope() {
    return this->scope;
}

void PLCSymbolTable::addFromLocal(PLCSymbol *symbol) {
    std::string name = symbol->getName();
    if(name.empty()){
        //TODO:提示添加了符号无名称
        std::cerr << "symbol should have a name." << std::endl;
    }
    int symbolId = symbol->getSymbolId();

    this->nameMap.insert(std::make_pair(name, symbol));
    this->idMap.insert(std::make_pair(symbolId, symbol));

    //添加本作用域内的符号
    if(this->recordMap.count(name)){
        SymbolRecord* record = this->recordMap[name];
        record->setMajorSymbol(symbol);
        record->setIfExist(true);
    }else{
        SymbolRecord* newRecord = SymbolRecord::makeRecord(name, true);
        newRecord->setMajorSymbol(symbol);
        this->recordMap.insert(std::make_pair(name, newRecord));
    }
}

PLCSymbol *PLCSymbolTable::getSymbolByNameFromLocalNameMap(std::string name) {
    if(this->nameMap.count(name)){
        return this->nameMap[name];
    }
    return nullptr;
}

PLCSymbol *PLCSymbolTable::getSymbolByIdFromLocal(int id) {
    if(this->idMap.count(id)){
        return this->idMap[id];
    }
    return nullptr;
}

const std::map<std::string, SymbolRecord *> &PLCSymbolTable::getRecordMap() const {
    return recordMap;
}

void PLCSymbolTable::addAlternativeSymbolsFromTable(PLCSymbolTable *another) {
     std::map<std::string, SymbolRecord*> anotherRecordMap = another->getRecordMap();
     for(auto item : anotherRecordMap){
         std::string name = item.first;
         SymbolRecord* anotherRecord = anotherRecordMap[name];
         //有相同的记录
         if(this->recordMap.count(name)){
            SymbolRecord* thisRecord = this->recordMap[name];
            thisRecord->linkRecord(anotherRecord);
         }else{ //没有相同名称的符号
             SymbolRecord* newRecord = SymbolRecord::makeRecord(name, false);
             this->recordMap.insert(std::make_pair(name, newRecord));
             newRecord->linkRecord(anotherRecord);
         }
     }
}

PLCSymbol *PLCSymbolTable::getSymbolByNameFromLocalRecord(std::string name) {
    if(this->recordMap.count(name)){
        SymbolRecord* record = recordMap[name];
        if(record->isIfExist()){ //符号存在，且有强符号
            return record->getMajorSymbol();
        }else{
            if(record->getAlternativeCount() == 1){ //符号不存在，但是替补无歧义
                return record->getFirstAlternativeSymbol();
            }else{ //符号不存在，替补有歧义
                return nullptr;
            }
        }
    }else{ //符号不存在，无替补
        return nullptr;
    }

    //TODO:不同情况下的未查找到应该区分
}

PLCSymbolTable::PLCSymbolTable(ImportScope *importSymbol, PLCScope *scope) :
    importSymbol(importSymbol), scope(scope) {

}

void PLCSymbolTable::addAlternativeSymbol(PLCSymbol *alternativeSymbol) {
    std::string name = alternativeSymbol->getName();
    SymbolRecord* thisRecord = this->recordMap[name];
    thisRecord->addAlternativeSymbol(alternativeSymbol);
}
